#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include "log.h"
#include "delay.h"

#define PCM_DEVICE "hw:1,0"
#define SAMPLE_RATE 48000
#define CHANNELS 10
#define FRAME_TIME_MS 20
#define OUTPUT_FILE_NAME "output.raw"

// 计算20ms对应的帧数
#define FRAMES_PER_BUFFER ((SAMPLE_RATE * FRAME_TIME_MS) / 1000)

int main() {
    snd_pcm_t *pcm_handle;
    snd_pcm_hw_params_t *params;
    unsigned int sample_rate = SAMPLE_RATE;
    int channels = CHANNELS;
    int dir;
    int rc;
    char *buffer;
    FILE *output_file;
    snd_pcm_uframes_t frames;
    unsigned int periods = 4;  // 周期数

    // 打开 PCM 设备
    rc = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0) {
        LOG_ERROR("无法打开 PCM 设备: %s", snd_strerror(rc));
        return 1;
    }

    // 分配硬件参数结构体
    snd_pcm_hw_params_alloca(&params);

    // 初始化参数
    rc = snd_pcm_hw_params_any(pcm_handle, params);
    if (rc < 0) {
        LOG_ERROR("无法初始化硬件参数: %s", snd_strerror(rc));
        return 1;
    }

    // 设置访问方式（交错模式）
    rc = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (rc < 0) {
        LOG_ERROR("无法设置访问方式: %s", snd_strerror(rc));
        return 1;
    }

    // 设置采样格式（16-bit 有符号小端）
    rc = snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE);
    if (rc < 0) {
        LOG_ERROR("无法设置采样格式: %s", snd_strerror(rc));
        return 1;
    }

    // 设置采样率
    rc = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &sample_rate, &dir);
    if (rc < 0) {
        LOG_ERROR("无法设置采样率: %s", snd_strerror(rc));
        return 1;
    }

    // 设置通道数
    rc = snd_pcm_hw_params_set_channels(pcm_handle, params, channels);
    if (rc < 0) {
        LOG_ERROR("无法设置通道数: %s", snd_strerror(rc));
        return 1;
    }

    // 设置缓冲区大小（4个周期）
    frames = FRAMES_PER_BUFFER;
    rc = snd_pcm_hw_params_set_period_size_near(pcm_handle, params, &frames, &dir);
    if (rc < 0) {
        LOG_ERROR("无法设置周期大小: %s", snd_strerror(rc));
        return 1;
    }

    // 设置缓冲区大小为4个周期
    rc = snd_pcm_hw_params_set_periods(pcm_handle, params, periods, 0);
    if (rc < 0) {
        LOG_ERROR("无法设置周期数: %s", snd_strerror(rc));
        return 1;
    }

    // 应用参数
    rc = snd_pcm_hw_params(pcm_handle, params);
    if (rc < 0) {
        LOG_ERROR("无法应用硬件参数: %s", snd_strerror(rc));
        return 1;
    }

    // 获取实际设置的参数
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    LOG_INFO("实际设置的帧数: %lu", frames);

    // 分配缓冲区
    buffer = malloc(frames * channels * 2);
    if (!buffer) {
        LOG_ERROR("内存分配失败");
        return 1;
    }

    // 打开输出文件
    output_file = fopen(OUTPUT_FILE_NAME, "wb");
    if (!output_file) {
        LOG_ERROR("无法打开输出文件");
        free(buffer);
        return 1;
    }

    LOG_INFO("正在录制音频（按 Ctrl+C 停止）...");
    LOG_INFO("采样率: %d Hz, 通道数: %d, 帧长: %lu frames (%.1f ms)",
             sample_rate, channels, frames, (float)frames * 1000 / sample_rate);

    while (1) {
        uint64_t start_time = rx_get_timestamp();
        // 阻塞方式读取音频数据
        rc = snd_pcm_readi(pcm_handle, buffer, frames);
        if (rc == -EPIPE) {
            LOG_ERROR("缓冲区欠载，重新准备设备");
            snd_pcm_prepare(pcm_handle);
            continue;
        } else if (rc < 0) {
            LOG_ERROR("读取错误: %s", snd_strerror(rc));
            break;
        }
        LOG_INFO("diff time = %lu buffer_size = %lu SAMPLE_RATE = %lu", rx_get_timestamp() - start_time, frames * channels * 2, SAMPLE_RATE);
        // 写入文件
        if (fwrite(buffer, frames * channels * 2, 1, output_file) != 1) {
            LOG_ERROR("文件写入失败");
            break;
        }
    }

    // 清理资源
    fclose(output_file);
    free(buffer);
    snd_pcm_close(pcm_handle);

    LOG_INFO("录制完成，音频已保存到 output.raw");
    return 0;
}